package network;

import gamemngr.GameMngr;

import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import java.util.TreeMap;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.locks.ReentrantLock;
import java.sql.Connection;
import java.sql.SQLException;

import Database.DBActions;

public class Server{

	public volatile static Map<Integer,NetworkGame> openGames = new TreeMap<Integer,NetworkGame>();
	public volatile static Map<Integer,NetworkGame> closedGames = new TreeMap<Integer,NetworkGame>();
	public volatile static PlayersSet players = new PlayersSet();
	public volatile static AtomicInteger ids = new AtomicInteger();
	public static final int serverPort = 40771;

	/**
	 * @param args
	 */
	public static void main(String[] args) {
		ServerSocket server = null;
		Socket socket = null;
		DBActions dbact = new DBActions();
		
		try {
			server = new ServerSocket(serverPort);
		} catch (IOException e) {
			e.printStackTrace();
		}
		
		while (true){
			try {
				socket = server.accept();
			} catch (IOException e) {
				e.printStackTrace();
			}
			NetworkPlayer player = new NetworkPlayer("",socket, ids.getAndIncrement());

			Server.players.add(player);
			new NewConnection(player, dbact).start();
		}
	}

	/**
	 * send the new game move to all of the players in the game 
	 * @param game
	 */
	public static void updateClients(GameMngr gameMngr){
		NetworkGame game = Server.closedGames.get(gameMngr.getGameID());
		game.informAll(new GameMngrMsg(gameMngr, "commit"));
	}
}

class PlayersSet {

	private Set<NetworkPlayer> players = new HashSet<NetworkPlayer>();
	private ReentrantLock lock = new ReentrantLock();

	public void add(NetworkPlayer player){
		lock.lock();
		try{
			players.add(player);
		} finally {
			lock.unlock();
		}
	}

	public void remove(NetworkPlayer player){
		lock.lock();
		try{
			players.remove(player);
		} finally {
			lock.unlock();
		}
	}

	public void sendOpenGamesToUnassigned(){
		lock.lock();
		try{
			for(NetworkPlayer player : players){
				NetworkMsg msg = new OpenedGamesMsg(Server.openGames);
				player.sendMsg(msg);
			}
		} finally {
			lock.unlock();
		}
	}
}